﻿using System;
using System.Runtime.Serialization;

namespace Sencha.Direct
{
	[DataContract, Serializable]
	public class JsError
	{
		[DataMember(Name = "isError", Order = 10)] // flag for dynamic languages
		public bool IsError { get { return true; } set { } }

		[DataMember(Name = "name", Order=1)]
		public string Name { get; set; }
		[DataMember(Name = "message", Order=3)]
		public string Message { get; set; }
		[DataMember(Name = "number", Order=2)]
		public int Number { get; set; }
		[DataMember(Name = "helpUrl", Order=4)]
		public string HelpUrl { get; set; }
		[DataMember(Name = "description", Order=5)]
		public string Description { get; set; }
		[DataMember(Name = "success", Order = 9)] // contract compability with FormActionResult and RecordsActionResult
		public bool Success { get { return false; } set { } }

		public JsError()
		{
			this.Name = Loc.GetErrorString("JsError_GenericName");
			this.Message = Loc.GetErrorString("JsError_GenericMessage");
			this.Description = Loc.GetErrorString("JsError_GenericDescription");
			Number = -1;
		}
		public JsError(string name, string message)
		{
			this.Name = name ?? Loc.GetErrorString("JsError_GenericName");
			this.Message = message ?? Loc.GetErrorString("JsError_GenericMessage");
			this.Description = Loc.GetErrorString("JsError_GenericDescription");
			Number = -1;
		}
		public JsError(Exception exc)
		{
			if (exc == null)
				throw new ArgumentNullException("exc");

			if (exc is Exceptions.RemoteInvocationException)
			{
				var rem = exc as Exceptions.RemoteInvocationException;

				this.Name = rem.OriginalError.Name;
				this.Message = rem.OriginalError.Message;
				this.HelpUrl = rem.OriginalError.HelpUrl;
				this.Description = rem.OriginalError.Description;
				this.Number = rem.OriginalError.Number;
			}
			else
			{
				this.Name = exc.GetType().FullName;
				this.Message = CollectMessages(exc, 0);
				this.HelpUrl = exc.HelpLink;
				this.Description = CollectTrace(exc);
				if (exc is System.ComponentModel.Win32Exception)
					this.Number = (exc as System.ComponentModel.Win32Exception).ErrorCode;
			}
		}

		private string CollectMessages(Exception exc, int depth)
		{
			if (exc.InnerException != null)
				return CollectMessages(exc.InnerException, depth + 1) + "\r\n" + exc.Message;

			return exc.Message;
		}
		private string CollectTrace(Exception exc)
		{
			if (exc.InnerException != null)
				return CollectTrace(exc.InnerException) + "/r/n" + exc.StackTrace;

			return exc.StackTrace;
		}

		public override string ToString()
		{
			return string.Format("Error: {1}, {0}", this.Message, this.Name);
		}
	}
}
